package forward.Module.Modules.Move;


import forward.Module.Module;
import forward.Module.ModuleType;
import forward.UI.ClientNotification;
import forward.Util.BlockUtils;
import forward.Util.ClientUtil;
import forward.Util.MSTimer;
import forward.api.EventHandler;
import forward.api.Events.World.*;
import forward.api.Value.Option;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;

import java.util.Arrays;
import java.util.List;

public class Scaffold extends Module {
    // public static ModeValue blockCount = new ModeValue("Scaffold", "Block Counter", "New", "Simple", "New");
    // public static BooleanValue safewalk = new BooleanValue("Scaffold", "SafeWalk", true);
    // public static BooleanValue esp = new BooleanValue("Scaffold", "ESP", false);
    // public static BooleanValue tower = new BooleanValue("Scaffold", "Tower", true);
    // public static BooleanValue swing = new BooleanValue("Scaffold", "Swing", false);
    // public static BooleanValue forcesprint = new BooleanValue("Scaffold", "Forcesprint", false);
    public static float curYaw = 0;

   // public static List<Block> blacklist;
    //private int width;
    //public Mode<Enum> ex = new Mode("Mode", "Mode", (Enum[])Exmode.values(), (Enum) Exmode.MinePlexCombat);
    //private Option<Boolean> ex = new Option<Boolean>("ex", "ex", true);
    private Option<Boolean> forcesprint = new Option<Boolean>("forcesprint", "forcesprint", false);
    private Option<Boolean> swing = new Option<Boolean>("swing", "swing", true);
    private Option<Boolean> tower = new Option<Boolean>("tower", "tower", false);
    //private Option<Boolean> esp = new Option<Boolean>("esp", "esp", false);
    public static Option<Boolean> safewalk = new Option<Boolean>("safewalk", "safewalk", true);
    //private Numbers<Double> ex = new Numbers<Double>("ex", "ex", 50.0, 0.0, 1000.0, 10.0);
    public Scaffold() {
        super("Scaffold", new String[] {"Scaffold"}, ModuleType.Move);
        this.addValues(forcesprint,swing,tower,safewalk);
    }
   public static List<Block> blacklist= Arrays.asList(Blocks.air, Blocks.water, Blocks.flowing_water, Blocks.lava, Blocks.flowing_lava, Blocks.sand, Blocks.enchanting_table, Blocks.beacon, Blocks.noteblock, Blocks.sand, Blocks.chest, Blocks.gravel, Blocks.ender_chest);
    @Override
    public void onEnable() {
        super.onEnable();
    }
    @Override
    public void onDisable() {
        super.onDisable();
        KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindSneak.getKeyCode(), false);
    }
    @EventHandler
    public void onPost(EventPostUpdate e) {
        curYaw = e.getYaw();
    }
    @EventHandler
    public void onRespawn(RespawnEvent e) {
        this.setEnabled(false);
        ClientUtil.sendClientMessage("Scaffold Disabled due to Respawn", ClientNotification.Type.INFO);
    }
    public static boolean isScaffoldBlock(ItemStack itemStack) {
        if (itemStack == null)
            return false;

        if (itemStack.stackSize <= 0)
            return false;

        if (!(itemStack.getItem() instanceof ItemBlock))
            return false;

        ItemBlock itemBlock = (ItemBlock) itemStack.getItem();

        // whitelist
        if (itemBlock.getBlock() == Blocks.glass)
            return true;

        // only fullblock
        if (!itemBlock.getBlock().isFullBlock())
            return false;

        return true;
    }
    // Minecraft Skid
    static IBlockState blockState(BlockPos pos) {
        //MCP
        return Minecraft.getMinecraft().theWorld.getBlockState(pos);
    }

    static Block getBlock(BlockPos pos) {
        //MCP
        return blockState(pos).getBlock();
    }

    //Recieve SideBlock Data
    public static BlockPos getSideBlock(BlockPos currentPos) {
        BlockPos pos = currentPos;
        if (getBlock(currentPos.add(0, -1, 0)) != Blocks.air && !(getBlock(currentPos.add(0, -1, 0)) instanceof BlockLiquid))
            return currentPos.add(0, -1, 0);

        double dist = 20;
        for (int x = -2; x <= 2; x++) {
            for (int y = -2; y <= 1; y++) {
                for (int z = -2; z <= 2; z++) {
                    BlockPos newPos = currentPos.add(x, 0, z);
                    double newDist = MathHelper.sqrt_double(x * x + y * y + z * z);
                    if (getBlock(newPos) != Blocks.air && !(getBlock(newPos) instanceof BlockLiquid)
                            && getBlock(newPos).getMaterial().isSolid() && newDist <= dist) {
                        pos = currentPos.add(x, y, z);
                        dist = newDist;
                    }
                }
            }
        }
        return pos;
    }

    // get Side Hit Data
    public static EnumFacing getSideHit(BlockPos currentPos, BlockPos sideBlock) {
        int xDiff = sideBlock.getX() - currentPos.getX();
        int yDiff = sideBlock.getY() - currentPos.getY();
        int zDiff = sideBlock.getZ() - currentPos.getZ();
        return yDiff != 0 ? EnumFacing.UP : xDiff <= -1 ? EnumFacing.EAST : xDiff >= 1 ? EnumFacing.WEST : zDiff <= -1 ? EnumFacing.SOUTH : zDiff >= 1 ? EnumFacing.NORTH : EnumFacing.DOWN;
    }
    private BlockPos blockUnder = null;
    private BlockPos blockBef = null;
    private EnumFacing facing = null;
    private MSTimer placeTimer = new MSTimer();
    @EventHandler
    public void onUpdate(EventPreUpdate event) {
        blockUnder = null;
        blockBef = null;
        if (Minecraft.getMinecraft().thePlayer.getCurrentEquippedItem() == null || Minecraft.getMinecraft().thePlayer.getCurrentEquippedItem().getItem() == null
                || !(Minecraft.getMinecraft().thePlayer.getCurrentEquippedItem().getItem() instanceof ItemBlock)) {
            return;
        }

        Minecraft.getMinecraft().thePlayer.setSprinting(false);

        BlockPos under = new BlockPos(Minecraft.getMinecraft().thePlayer.posX, Minecraft.getMinecraft().thePlayer.posY - 0.01, Minecraft.getMinecraft().thePlayer.posZ);
        if (BlockUtils.getBlock(under).getMaterial() == Material.air) {
            blockUnder = under;
            for (EnumFacing facing : EnumFacing.values()) {
                BlockPos offset = blockUnder.offset(facing);
                if (BlockUtils.getBlock(offset).getMaterial() != Material.air) {
                    this.facing = facing;
                    blockBef = offset;
                    break;
                }
            }
        }

        event.setYaw(Minecraft.getMinecraft().thePlayer.rotationYaw > 0.0F ? Minecraft.getMinecraft().thePlayer.rotationYaw - 180.0F
                : Minecraft.getMinecraft().thePlayer.rotationYaw + 180.0F);
        event.setPitch(82.0F);
    }

    @EventHandler
    public void onTick(EventTick event) {
        BlockPos expanded = new BlockPos(Minecraft.getMinecraft().thePlayer.posX + Minecraft.getMinecraft().thePlayer.motionX * 2, Minecraft.getMinecraft().thePlayer.posY - 0.01,
                Minecraft.getMinecraft().thePlayer.posZ + Minecraft.getMinecraft().thePlayer.motionZ * 2);
        BlockPos under = new BlockPos(Minecraft.getMinecraft().thePlayer.posX, Minecraft.getMinecraft().thePlayer.posY - 0.01, Minecraft.getMinecraft().thePlayer.posZ);
        if (BlockUtils.getBlock(expanded).getMaterial() == Material.air
                || BlockUtils.getBlock(under).getMaterial() == Material.air) {
            // Minecraft.getMinecraft().gameSettings.keyBindSneak.pressed = true;
        } else {
            Minecraft.getMinecraft().gameSettings.keyBindSneak.pressed = false;
        }
    }

    @EventHandler
    public void onMove(EventMove e) {
       // e.setSafeWalk(true);


        if (!Minecraft.getMinecraft().thePlayer.onGround || !Minecraft.getMinecraft().thePlayer.isCollidedVertically
                || Minecraft.getMinecraft().thePlayer.movementInput.jump) {
            e.x = 0;
            e.z = 0;
        }
    }

    @EventHandler
    public void onLateUpdate(EventPostUpdate event) {
        if (blockUnder==null){
            return;
        }
        try{
            MovingObjectPosition pos = Minecraft.getMinecraft().theWorld.rayTraceBlocks(this.getVec3(blockUnder).addVector(0.5, 0.5, 0.5),
                    this.getVec3(blockBef).addVector(0.5, 0.5, 0.5));
            Vec3 hitVec = pos.hitVec;
            Minecraft.getMinecraft().thePlayer.swingItem();
            Minecraft.getMinecraft().playerController.onPlayerRightClick(Minecraft.getMinecraft().thePlayer, Minecraft.getMinecraft().theWorld, Minecraft.getMinecraft().thePlayer.getCurrentEquippedItem(),
                    blockBef, pos.sideHit, hitVec);

            this.placeTimer.reset();
        }catch (Exception e){

        }




        // sendPacket(new C08PacketPlayerBlockPlacement(blockBef,
        // pos.sideHit.getIndex(), Minecraft.getMinecraft().thePlayer.getCurrentEquippedItem(), f, f1, f2));
    }

    private Vec3 getVec3(BlockPos blockPos) {
        return new Vec3(blockPos.getX(), blockPos.getY(), blockPos.getZ());
    }
}
